package edu.northwestern.cbits.purple_robot_manager.probes.builtin;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Build;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import edu.northwestern.cbits.purple_robot_manager.R;
import edu.northwestern.cbits.purple_robot_manager.activities.settings.FlexibleListPreference;
import edu.northwestern.cbits.purple_robot_manager.logging.LogManager;
import edu.northwestern.cbits.purple_robot_manager.probes.Probe;
public class SoftwareInformationProbe extends Probe
{
private static final String CODENAME = "CODENAME";
private static final String INCREMENTAL = "INCREMENTAL";
private static final String RELEASE = "RELEASE";
private static final String SDK_INT = "SDK_INT";
private static final String APP_NAME = "APP_NAME";
private static final String PACKAGE_NAME = "PACKAGE_NAME";
private static final String PACKAGE_VERSION_NAME = "PACKAGE_VERSION_NAME";
private static final String PACKAGE_VERSION_CODE = "PACKAGE_VERSION_CODE";
private static final String INSTALLED_APPS = "INSTALLED_APPS";
private static final String INSTALLED_APP_COUNT = "INSTALLED_APP_COUNT";
private static final boolean DEFAULT_ENABLED = true;
private static final String ENABLED = "config_probe_software_enabled";
private static final String FREQUENCY = "config_probe_software_frequency";
private long _lastCheck = 0;
@Override
public String getPreferenceKey() {
return "built_in_software";
}
@Override
public String name(Context context)
{
return "edu.northwestern.cbits.purple_robot_manager.probes.builtin.SoftwareInformationProbe";
}
@Override
public String title(Context context)
{
return context.getString(R.string.title_software_info_probe);
}
@Override
public String probeCategory(Context context)
{
return context.getResources().getString(R.string.probe_device_info_category);
}
@Override
public void enable(Context context)
{
SharedPreferences prefs = Probe.getPreferences(context);
Editor e = prefs.edit();
e.putBoolean(SoftwareInformationProbe.ENABLED, true);
e.commit();
}
@Override
public void disable(Context context)
{
SharedPreferences prefs = Probe.getPreferences(context);
Editor e = prefs.edit();
e.putBoolean(SoftwareInformationProbe.ENABLED, false);
e.commit();
}
@Override
public boolean isEnabled(Context context)
{
SharedPreferences prefs = Probe.getPreferences(context);
if (super.isEnabled(context))
{
long now = System.currentTimeMillis();
if (prefs.getBoolean(SoftwareInformationProbe.ENABLED, SoftwareInformationProbe.DEFAULT_ENABLED))
{
synchronized (this)
{
long freq = Long.parseLong(prefs.getString(SoftwareInformationProbe.FREQUENCY, Probe.DEFAULT_FREQUENCY));
if (now - this._lastCheck > freq)
{
Bundle bundle = new Bundle();
bundle.putString("PROBE", this.name(context));
bundle.putLong("TIMESTAMP", System.currentTimeMillis() / 1000);
bundle.putString(SoftwareInformationProbe.CODENAME, Build.VERSION.CODENAME);
bundle.putString(SoftwareInformationProbe.INCREMENTAL, Build.VERSION.INCREMENTAL);
bundle.putString(SoftwareInformationProbe.RELEASE, Build.VERSION.RELEASE);
bundle.putInt(SoftwareInformationProbe.SDK_INT, Build.VERSION.SDK_INT);
try
{
PackageManager pm = context.getApplicationContext().getPackageManager();
List<ApplicationInfo> infos = pm.getInstalledApplications(0);
ArrayList<Bundle> installed = new ArrayList<>();
for (ApplicationInfo info : infos)
{
try
{
Bundle appBundle = new Bundle();
appBundle.putString(SoftwareInformationProbe.APP_NAME, info.loadLabel(pm).toString());
appBundle.putString(SoftwareInformationProbe.PACKAGE_NAME, info.packageName);
try
{
PackageInfo pkgInfo = pm.getPackageInfo(info.packageName, 0);
appBundle.putString(SoftwareInformationProbe.PACKAGE_VERSION_NAME, pkgInfo.versionName);
appBundle.putInt(SoftwareInformationProbe.PACKAGE_VERSION_CODE, pkgInfo.versionCode);
}
catch (Resources.NotFoundException e)
{
appBundle.putString(SoftwareInformationProbe.PACKAGE_VERSION_NAME, "");
appBundle.putInt(SoftwareInformationProbe.PACKAGE_VERSION_CODE, -1);
}
installed.add(appBundle);
}
catch (PackageManager.NameNotFoundException e)
{
e.printStackTrace();
}
}
bundle.putParcelableArrayList(SoftwareInformationProbe.INSTALLED_APPS, installed);
bundle.putInt(SoftwareInformationProbe.INSTALLED_APP_COUNT, installed.size());
}
catch (RuntimeException e)
{
LogManager.getInstance(context).logException(e);
}
this.transmitData(context, bundle);
this._lastCheck = now;
}
}
return true;
}
}
return false;
}
@Override
public String summarizeValue(Context context, Bundle bundle)
{
String release = bundle.getString(SoftwareInformationProbe.RELEASE);
int count = (int) bundle.getDouble(SoftwareInformationProbe.INSTALLED_APP_COUNT);
return String.format(context.getResources().getString(R.string.summary_software_info_probe), release, count);
}
private Bundle bundleForAppArray(Context context, ArrayList<Bundle> objects)
{
Bundle bundle = new Bundle();
ArrayList<String> keys = new ArrayList<>();
for (int i = 0; i < objects.size(); i++)
{
Bundle value = objects.get(i);
String name = value.getString(SoftwareInformationProbe.APP_NAME);
String key = value.getString(SoftwareInformationProbe.PACKAGE_NAME);
keys.add(key);
bundle.putString(key, name);
}
bundle.putStringArrayList("KEY_ORDER", keys);
return bundle;
}
@Override
public Bundle formattedBundle(Context context, Bundle bundle)
{
Bundle formatted = super.formattedBundle(context, bundle);
@SuppressWarnings("unchecked")
ArrayList<Bundle> array = (ArrayList<Bundle>) bundle.get(SoftwareInformationProbe.INSTALLED_APPS);
int count = (int) bundle.getDouble(SoftwareInformationProbe.INSTALLED_APP_COUNT);
Bundle appsBundle = this.bundleForAppArray(context, array);
formatted.putBundle(String.format(context.getString(R.string.display_installed_apps_title), count), appsBundle);
formatted.putString(context.getString(R.string.display_android_version_title), bundle.getString(SoftwareInformationProbe.RELEASE));
return formatted;
}
@Override
public Map<String, Object> configuration(Context context)
{
Map<String, Object> map = super.configuration(context);
SharedPreferences prefs = Probe.getPreferences(context);
long freq = Long.parseLong(prefs.getString(SoftwareInformationProbe.FREQUENCY, Probe.DEFAULT_FREQUENCY));
map.put(Probe.PROBE_FREQUENCY, freq);
return map;
}
@Override
public void updateFromMap(Context context, Map<String, Object> params)
{
super.updateFromMap(context, params);
if (params.containsKey(Probe.PROBE_FREQUENCY))
{
Object frequency = params.get(Probe.PROBE_FREQUENCY);
if (frequency instanceof Double)
{
frequency = ((Double) frequency).longValue();
}
if (frequency instanceof Long)
{
SharedPreferences prefs = Probe.getPreferences(context);
Editor e = prefs.edit();
e.putString(SoftwareInformationProbe.FREQUENCY, frequency.toString());
e.commit();
}
}
}
@Override
public String summary(Context context)
{
return context.getString(R.string.summary_software_info_probe_desc);
}
@Override
@SuppressWarnings("deprecation")
public PreferenceScreen preferenceScreen(Context context, PreferenceManager manager)
{
PreferenceScreen screen = super.preferenceScreen(context, manager);
screen.setTitle(this.title(context));
screen.setSummary(R.string.summary_software_info_probe_desc);
CheckBoxPreference enabled = new CheckBoxPreference(context);
enabled.setTitle(R.string.title_enable_probe);
enabled.setKey(SoftwareInformationProbe.ENABLED);
enabled.setDefaultValue(SoftwareInformationProbe.DEFAULT_ENABLED);
screen.addPreference(enabled);
FlexibleListPreference duration = new FlexibleListPreference(context);
duration.setKey(SoftwareInformationProbe.FREQUENCY);
duration.setEntryValues(R.array.probe_low_frequency_values);
duration.setEntries(R.array.probe_low_frequency_labels);
duration.setTitle(R.string.probe_frequency_label);
duration.setDefaultValue(Probe.DEFAULT_FREQUENCY);
screen.addPreference(duration);
return screen;
}
@Override
public JSONObject fetchSettings(Context context)
{
JSONObject settings = super.fetchSettings(context);
try
{
JSONObject frequency = new JSONObject();
frequency.put(Probe.PROBE_TYPE, Probe.PROBE_TYPE_LONG);
JSONArray values = new JSONArray();
String[] options = context.getResources().getStringArray(R.array.probe_low_frequency_values);
for (String option : options)
{
values.put(Long.parseLong(option));
}
frequency.put(Probe.PROBE_VALUES, values);
settings.put(Probe.PROBE_FREQUENCY, frequency);
}
catch (JSONException e)
{
LogManager.getInstance(context).logException(e);
}
return settings;
}
public String assetPath(Context context)
{
return "software-information-probe.html";
}
}